home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
lib
/
c
/
hash
/
RCS
/
Hash_CreateEntry.c,v
< prev
next >
Wrap
Text File
|
1989-11-30
|
6KB
|
267 lines
head 1.3;
branch ;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.3
date 88.07.28.17.57.23; author ouster; state Exp;
branches ;
next 1.2;
1.2
date 88.07.25.10.53.29; author ouster; state Exp;
branches ;
next 1.1;
1.1
date 88.06.20.09.30.19; author ouster; state Exp;
branches ;
next ;
desc
@@
1.3
log
@Lint.
@
text
@/*
* Hash_CreateEntry.c --
*
* Source code for the Hash_CreateEntry library procedure.
*
* Copyright 1988 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: Hash_CreateEntry.c,v 1.2 88/07/25 10:53:29 ouster Exp $ SPRITE (Berkeley)";
#endif not lint
#include <hash.h>
#include <list.h>
#include <stdlib.h>
#include <string.h>
/*
* Utility procedures defined in other files:
*/
extern Hash_Entry * HashChainSearch();
extern int Hash();
/*
* The following defines the ratio of # entries to # buckets
* at which we rebuild the table to make it larger.
*/
static rebuildLimit = 3;
/*
*---------------------------------------------------------
*
* RebuildTable --
* This local routine makes a new hash table that
* is larger than the old one.
*
* Results:
* None.
*
* Side Effects:
* The entire hash table is moved, so any bucket numbers
* from the old table are invalid.
*
*---------------------------------------------------------
*/
static void
RebuildTable(tablePtr)
Hash_Table *tablePtr; /* Table to be enlarged. */
{
int oldSize;
int bucket;
List_Links *oldBucketPtr;
register Hash_Entry *hashEntryPtr;
register List_Links *oldHashList;
oldBucketPtr = tablePtr->bucketPtr;
oldSize = tablePtr->size;
/*
* Build a new table 4 times as large as the old one.
*/
Hash_InitTable(tablePtr, tablePtr->size * 4, tablePtr->keyType);
for (oldHashList = oldBucketPtr; oldSize > 0; oldSize--, oldHashList++) {
while (!List_IsEmpty(oldHashList)) {
hashEntryPtr = (Hash_Entry *) List_First(oldHashList);
List_Remove((List_Links *) hashEntryPtr);
switch (tablePtr->keyType) {
case HASH_STRING_KEYS:
bucket = Hash(tablePtr, (Address) hashEntryPtr->key.name);
break;
case HASH_ONE_WORD_KEYS:
bucket = Hash(tablePtr, (Address) hashEntryPtr->key.ptr);
break;
default:
bucket = Hash(tablePtr, (Address) hashEntryPtr->key.words);
break;
}
List_Insert((List_Links *) hashEntryPtr,
LIST_ATFRONT(&(tablePtr->bucketPtr[bucket])));
tablePtr->numEntries++;
}
}
free((Address) oldBucketPtr);
}
/*
*---------------------------------------------------------
*
* Hash_CreateEntry --
*
* Searches a hash table for an entry corresponding to
* key. If no entry is found, then one is created.
*
* Results:
* The return value is a pointer to the entry. If *newPtr
* isn't NULL, then *newPtr is filled in with TRUE if a
* new entry was created, and FALSE if an entry already existed
* with the given key.
*
* Side Effects:
* Memory may be allocated, and the hash buckets may be modified.
*---------------------------------------------------------
*/
Hash_Entry *
Hash_CreateEntry(tablePtr, key, newPtr)
register Hash_Table *tablePtr; /* Hash table to search. */
Address key; /* A hash key. */
Boolean *newPtr; /* Filled in with TRUE if new entry
* created, FALSE otherwise. */
{
register Hash_Entry *hashEntryPtr;
register int *hashKeyPtr;
register int *keyPtr;
List_Links *hashList;
keyPtr = (int *) key;
hashList = &(tablePtr->bucketPtr[Hash(tablePtr, (Address) keyPtr)]);
hashEntryPtr = HashChainSearch(tablePtr, (Address) keyPtr, hashList);
if (hashEntryPtr != (Hash_Entry *) NULL) {
if (newPtr != NULL) {
*newPtr = FALSE;
}
return hashEntryPtr;
}
/*
* The desired entry isn't there. Before allocating a new entry,
* see if we're overloading the buckets. If so, then make a
* bigger table.
*/
if (tablePtr->numEntries >= rebuildLimit * tablePtr->size) {
RebuildTable(tablePtr);
hashList = &(tablePtr->bucketPtr[Hash(tablePtr, (Address) keyPtr)]);
}
tablePtr->numEntries += 1;
/*
* Not there, we have to allocate. If the string is longer
* than 3 bytes, then we have to allocate extra space in the
* entry.
*/
switch (tablePtr->keyType) {
case HASH_STRING_KEYS:
hashEntryPtr = (Hash_Entry *) malloc((unsigned)
(sizeof(Hash_Entry) + strlen((char *) keyPtr) - 3));
strcpy(hashEntryPtr->key.name, (char *) keyPtr);
break;
case HASH_ONE_WORD_KEYS:
hashEntryPtr = (Hash_Entry *) malloc(sizeof(Hash_Entry));
hashEntryPtr->key.ptr = (Address) keyPtr;
break;
case 2:
hashEntryPtr =
(Hash_Entry *) malloc(sizeof(Hash_Entry) + sizeof(int));
hashKeyPtr = hashEntryPtr->key.words;
*hashKeyPtr++ = *keyPtr++;
*hashKeyPtr = *keyPtr;
break;
default: {
register n;
n = tablePtr->keyType;
hashEntryPtr = (Hash_Entry *)
malloc((unsigned) (sizeof(Hash_Entry)
+ (n - 1) * sizeof(int)));
hashKeyPtr = hashEntryPtr->key.words;
do {
*hashKeyPtr++ = *keyPtr++;
} while (--n);
break;
}
}
hashEntryPtr->clientData = (ClientData) NULL;
List_Insert((List_Links *) hashEntryPtr, LIST_ATFRONT(hashList));
if (newPtr != NULL) {
*newPtr = TRUE;
}
return hashEntryPtr;
}
@
1.2
log
@Lint.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: Hash_CreateEntry.c,v 1.1 88/06/20 09:30:19 ouster Exp $ SPRITE (Berkeley)";
d162 2
a163 2
hashEntryPtr = (Hash_Entry *) malloc(sizeof(Hash_Entry) +
strlen((char *) keyPtr) - 3);
d182 2
a183 1
malloc(sizeof(Hash_Entry) + (n - 1) * sizeof(int));
@
1.1
log
@Initial revision
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: proto.c,v 1.2 88/03/11 08:39:08 ouster Exp $ SPRITE (Berkeley)";
d20 4
a23 2
#include "hash.h"
#include "list.h"
@